﻿
Imports System.IO
Imports std

Public Class randomfile
    Implements ICloneable

    Public Class selector
        Public dir As String = emptyString
        Public filter As String = emptyString
        Public includeSubFolders As Boolean = False

        Public Sub New()
        End Sub

        Public Sub New(ByVal idir As String, ByVal ifilter As String, ByVal iIncludeSubFolders As Boolean)
            copy(dir, idir)
            copy(filter, ifilter)
            copy(includeSubFolders, iIncludeSubFolders)
        End Sub
    End Class

    Public Const defaultRefreshMS As Int64 = 30 * 60 * 1000
    Protected _refreshMS As Int64 = defaultRefreshMS
    Protected _files As vector(Of String) = Nothing
    Protected _selectors As vector(Of selector) = Nothing
#If Not PocketPC AndAlso Not Smartphone Then
    Protected WithEvents _timer As Timers.Timer = Nothing
#Else
    Protected WithEvents _timer As System.Windows.Forms.Timer = Nothing
#End If

    Public Function initial(ByVal dir As String, ByRef filter As String, ByVal includeSubFolders As Boolean) As Boolean
        If _files Is Nothing Then
            _files = New vector(Of String)
        Else
            _files.clear()
        End If

        If _selectors Is Nothing Then
            _selectors = New vector(Of selector)
        Else
            _selectors.clear()
        End If

        If _timer Is Nothing Then
#If Not PocketPC AndAlso Not Smartphone Then
            _timer = New Timers.Timer()
#Else
            _timer = New System.Windows.Forms.Timer()
#End If
        End If

        refreshMS = defaultRefreshMS

        Return add(dir, filter, includeSubFolders)
    End Function

    Protected Function addImpl(ByVal dir As String, ByVal filter As String, ByVal includeSubFolders As Boolean) As Boolean
        Dim strs() As String = Nothing
        Try
#If Not PocketPC AndAlso Not Smartphone Then
            strs = Directory.GetFiles(dir, filter, ifoper(includeSubFolders _
                                                          , SearchOption.AllDirectories _
                                                          , SearchOption.TopDirectoryOnly))
#Else
            strs = Directory.GetFiles(dir, filter)
#End If
        Catch ex As Exception
            raiseError("cannot get filelist, dir " + dir + ", filter " + filter, errorHandle.errorType.exclamation)
            Return False
        End Try

        If strs.Length() > 0 Then
            Dim i As Int32
            For i = 0 To strs.Length() - 1
                If files().find(strs(i)) = npos Then
                    files().push_back(strs(i))
                End If
            Next
        End If

        Return True
    End Function

    Public Function add(ByVal selector As selector) As Boolean
        Return add(selector.dir, selector.filter, selector.includeSubFolders)
    End Function

    Public Function add(ByVal dir As String, ByVal filter As String, ByVal includeSubFolders As Boolean) As Boolean
        dir = fullpath(dir)
        selectors().push_back(New selector(dir, filter, includeSubFolders))

        Return addImpl(dir, filter, includeSubFolders)
    End Function

    Public Function [get]() As String
        If files().size() = 0 Then
            Return Nothing
        End If

        Dim rtn As Int64
        rtn = rnd(0, files().size(), True)
        While Not File.Exists(files(rtn)) AndAlso files().size() > 0
            files().erase(rtn)
            rtn = rnd(0, files().size(), True)
        End While

        If files().size() > 0 Then
            Return files()(rtn)
        Else
            Return Nothing
        End If
    End Function

    Public Function files() As vector(Of String)
        assert(Not _files Is Nothing, "_files is nothing before calling files() function.")
        Return _files
    End Function

    Public Function selectors() As vector(Of selector)
        assert(Not _selectors Is Nothing, "_selectors is nothing before calling selectors() function.")
        Return _selectors
    End Function

#If Not PocketPC AndAlso Not Smartphone Then
    Public Function timer() As Timers.Timer
#Else
    Public Function timer() As System.Windows.Forms.Timer
#End If
        assert(Not _timer Is Nothing, "_timer is nothing before calling timer() function.")
        Return _timer
    End Function

    Public Property refreshMS() As Int64
        Get
            Return _refreshMS
        End Get
        Set(ByVal value As Int64)
            _refreshMS = value
            timer().Interval = value
#If Not PocketPC AndAlso Not Smartphone Then
            timer().Start()
#Else
            timer().Enabled = True
#End If
        End Set
    End Property

    Public Sub New()
        assert(initial(".", "thisfilecannotbeexisting.thissuffixcannotbeexisting", True) _
               , "cannot initialize randomfile.")
    End Sub

    Public Sub New(ByVal dir As String, ByVal filter As String, ByVal includeSubFolders As Boolean)
        If Not initial(dir, filter, includeSubFolders) Then
            raiseError("cannot initialize randomfile, dir " + dir + ", filter " + filter, errorHandle.errorType.warning)
        End If
    End Sub

    Public Shared Function create(ByVal dir As String, ByVal filter As String _
                                , ByVal includeSubFolders As Boolean) As randomfile
        Dim rtn As randomfile = Nothing
        rtn = New randomfile()
        If rtn.add(dir, filter, includeSubFolders) Then
            Return rtn
        Else
            Return Nothing
        End If
    End Function

    Public Shared Sub unittest()
        Dim rndf As randomfile = Nothing
        rndf = New randomfile()

        Dim i As Int64
        For i = 0 To rndf.files().size() - 1
            Console.WriteLine(rndf.files(i))
        Next
    End Sub

    Public Function Clone() As Object Implements System.ICloneable.Clone
        Dim rtn As randomfile = Nothing
        rtn = New randomfile()
        copy(rtn._files, _files)

        Return rtn
    End Function

    Protected Overrides Sub Finalize()
#If Not PocketPC AndAlso Not Smartphone Then
        timer().Stop()
#Else
        timer().Enabled = False
#End If
        timer().Dispose()
        _timer = Nothing
        MyBase.Finalize()
    End Sub

#If Not PocketPC AndAlso Not Smartphone Then
    Private Sub _timer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles _timer.Elapsed
#Else
    Private Sub _timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles _timer.Tick
#End If
        Dim i As Int64
        For i = 0 To selectors().size() - 1
            addImpl(selectors()(i).dir, selectors()(i).filter, selectors()(i).includeSubFolders)
        Next
    End Sub
End Class
